﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenQA.Selenium;
using System.Text.RegularExpressions;
using System.Windows.Controls;
using Serilog;
using ToolApp.Common;

namespace ToolApp.EdgeRewards;

public class Searches
{
    private readonly string _breakElem;
    private readonly string _numElem;
    private readonly string _totalId;
    private readonly string _loginClickElem;
    private readonly EdgeRewardsBase _sef;

    public Searches(EdgeRewardsBase sef)
    {
        _sef = sef;
        _breakElem = "//*[@id=\"userPointsBreakdown\"]/div/div[2]/div/div[1]/div/div[2]/mee-rewards-user-points-details/div/div/div/div/p[3]";
        _numElem = "//*[@id=\"userPointsBreakdown\"]/div/div[2]/div/div[1]/div/div[2]/mee-rewards-user-points-details/div/div/div/div/p[2]/b";
        _totalId = "id_rc";
        _loginClickElem = "//*[@id=\"b_idProviders\"]/li/a";
        if (sef.IsMobile)
        {
            _breakElem = "//*[@id=\"userPointsBreakdown\"]/div/div[2]/div/div[2]/div/div[2]/mee-rewards-user-points-details/div/div/div/div/p[3]";
            _numElem = "//*[@id=\"userPointsBreakdown\"]/div/div[2]/div/div[2]/div/div[2]/mee-rewards-user-points-details/div/div/div/div/p[2]/b";
            _totalId = "fly_id_rc";
            _loginClickElem = "//*[@id=\"HBSignIn\"]/a[1]";
        }
    }

    /// <summary>
    /// 开始搜索任务
    /// </summary>
    /// <returns></returns>
    public async Task<bool> BingSearches()
    {
        var num = CheckTask();
        if (num == 0)
        {
            return false;
        }
        var data = await GetBaiduRank(num);
        if (data == null)
        {
            Log.Error("获取百度指数关键字失败");
            return false;
        }

        foreach (var info in data)
        {
            var word = info["entityName"]?.ToString();
            if (string.IsNullOrWhiteSpace(word))
            {
                continue;
            }

            var total = BingSearch(word);
            if (total <= _sef.LastTotal)
            {
                var relatedTerms = await GetRelatedTerms(word);
                if (relatedTerms != null)
                {
                    for (var i = 1; i < relatedTerms.Count; i++)
                    {
                        total = BingSearch(relatedTerms[i].ToString());
                        if (total > _sef.LastTotal)
                        {
                            break;
                        }

                        var t = new Random().Next(31, 50);
                        Log.Information("搜索两次无法获得积分，等待{0}秒..", t);
                        Thread.Sleep(TimeSpan.FromSeconds(t));
                    }
                }
            }

            _sef.LastTotal = total;
            Thread.Sleep(TimeSpan.FromSeconds(new Random().Next(8, 12)));
        }
        return true;
    }

    /// <summary>
    /// 开始cn.bing.com搜索
    /// </summary>
    /// <param name="word"></param>
    /// <returns></returns>
    private int BingSearch(string word)
    {
        _sef.WebDriver!.Navigate().GoToUrl("https://cn.bing.com/");
        var searchbar = _sef.WaitUntilClickable(By.Id("sb_form_q"));
        searchbar.SendKeys(word);
        searchbar.Submit();
        Thread.Sleep(TimeSpan.FromSeconds(2));
        CheckLogin();
        var txt = _sef.WebDriver.FindElement(By.Id(_totalId)).Text;
        Log.Information("上次积分：{0}，当前积分：{1}，{2}", _sef.LastTotal, int.TryParse(txt, out var total) ? total : txt, word);
        return total;
    }

    /// <summary>
    /// 检查任务状态
    /// </summary>
    /// <returns></returns>
    private int CheckTask()
    {
        Log.Information("检查今日搜索任务完成情况...");
        _sef.WebDriver!.Navigate().GoToUrl("https://rewards.bing.com/pointsbreakdown");
        var txtBreak = _sef.WebDriver.FindElement(By.XPath(_breakElem)).Text;
        var txtNum = _sef.WebDriver.FindElement(By.XPath(_numElem)).Text;
        if (string.IsNullOrWhiteSpace(txtNum) || string.IsNullOrWhiteSpace(txtBreak))
        {
            Log.Error("未找到对应的控件信息，跳过该帐号 {0} {1}", txtBreak, txtNum);
            return 0;
        }

        Log.Information("今日已获得：{0}，{1}", txtNum, txtBreak);
        var txt = Regex.Replace(txtBreak, ".* (\\d+) .* (\\d+) [^0-9]*", "$1|$2");
        var nums = txt.Split("|");
        var num = (Convert.ToInt32(nums[0]) - Convert.ToInt32(txtNum)) / Convert.ToInt32(nums[1]);
        Log.Information("搜索剩余次数：" + num);
        if (num != 0)
        {
            return num;
        }
        Log.Information("已全部完成！");
        return 0;
    }

    /// <summary>
    /// 检查搜索
    /// </summary>
    private void CheckLogin()
    {
        string txt;
        if (_sef.IsMobile)
        {
            var mHamburger = _sef.WaitUntilClickable(By.Id("mHamburger"));
            mHamburger.Click();
            txt = _sef.WebDriver!.FindElement(By.Id("hb_s")).Text;
        }
        else
        {
            txt = _sef.WaitUntilClickable(By.Id("id_a")).GetAttribute("value");
        }

        if (txt != "登录")
        {
            return;
        }

        Log.Information("进行搜索页登录...");
        if (!_sef.IsMobile)
        {
            _sef.WebDriver!.FindElement(By.Id("id_a")).Click();
        }

        _sef.WebDriver!.FindElement(By.XPath(_loginClickElem)).Click();
        if (_sef.IsMobile)
        {
            _sef.WebDriver.FindElement(By.Id("mHamburger")).Click();
        }
        Thread.Sleep(TimeSpan.FromSeconds(5));
    }

    private static async Task<JArray?> GetBaiduRank(int topNum)
    {
        var date = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
        var data = new
        {
            topNum,
            startDate = date,
            endDate = date,
            channel = "feed",
            type = "brand",
            trade1 = 101,
            trade2 = 1054,
            rankType = "daily"
        };
        var resp = await HttpHelper.PostAsync("https://index.baidu.com/insight/brand/queryTradeRank",
            JsonConvert.SerializeObject(data));
        if (string.IsNullOrEmpty(resp))
        {
            return null;
        }

        return JObject.Parse(resp)["data"]?["data"] as JArray;
    }

    private static async Task<JArray?> GetRelatedTerms(string word)
    {
        var resp = await HttpHelper.GetAsync($"https://api.bing.com/osjson.aspx?query={word}");
        if (string.IsNullOrEmpty(resp))
        {
            return null;
        }

        return JArray.Parse(resp)[1] as JArray;
    }
}